{% extends 'base.html' %}
{% block body %}
{% raw %}
  <script src="static/js/polyfill.min.js"></script>
  <script src="static/js/vue.js"></script>
  <script src="static/semantic/semantic-ui-vue.min.js"></script>

  <style>
    .table-wrapper {
      overflow-x: auto;
      padding-bottom: 1em;
    }
    ::-webkit-scrollbar-track {
      -webkit-box-shadow: inset 0 0 8px rgba(178, 178, 178, 0.3) !important;
      background-color: #F5F5F5 !important;
    }
    ::-webkit-scrollbar {
      width: 8px !important;
      height: 8px !important;
      background-color: #F5F5F5 !important;
    }
    ::-webkit-scrollbar-thumb {
      background-color: #c3c3c3 !important;
      border: 8px solid #b4b4b4 !important;
    }

    .visible-app {
      display: block !important;
    }

    .preview-image {
      border-radius: 5px;
      height: 50px;
      cursor: pointer;
    }

    .full-preview-image {
      max-height: 400px;
      max-width: 400px;
    }

    .fade-enter-active, .fade-leave-active {
      transition: opacity 0.5s ease-in-out;
    }

    .fade-enter-to {
      opacity: 1;
      height: 50px;
    }

    .fade-enter, .fade-leave-to {
      opacity: 0;
      height: 0;
    }

    .pagination {
      height: 10px !important;
    }

    .pagination-size {
      border: none;
      background: none;
    }

    .order {
      cursor: pointer;
    }

    .order.up, .order.down {
      font-weight: bold;
    }

    .actions-card {

    }

    .db-card {
        background: #f7f7f7;
        border-radius: 5px;
        padding: 2em;
    }

    .action-buttons {
        display: flex;
        flex-direction: column;
    }

    .align-grid {
        display: grid !important;
    }

    .trash:hover {
        color: rgb(255, 13, 23);
    }

    @media screen and (max-width: 768px) {
      .full-preview-image {
        max-height: 250px;
        max-width: 330px;
      }
    }
  </style>

  <div id="vue_loader" class="ui large text loader loading active">Loading ...</div>

  <div class="ui " id="app" :class="{'visible-app': vue_loaded}" style="display: none">

  <!-- Main content -->
  <center class="center">

  <div class="ui container">
    <div class="wrapper">

      <!-- Statistics -->
      <div class="ui three column centered grid stackable">
        <div class="row">
          
          <!-- Total tasks -->
          <div class="column center aligned align-grid">
            <div class="ui db-card">
              <div class="ui statistic small">
                <!-- Project loading -->
                <center v-if="!project_loaded" style="margin-bottom: 3px">
                  <div class="ui loader loading active inline"></div>
                </center>
                <!-- Number -->
                <span class="value" v-else>
                  <animated-number :number="project.task_count"></animated-number>
                </span>
                <span class="label">Tasks</span>
                <span class="sub-label">
                  <i class="word-break" v-if="project.multi_session_mode">{{ project.source_storage.readable_path }}</i>
                  <span data-tooltip="Source storage sync in progress">
                    <i class="ui loader loading active inline mini" v-if="project.source_syncing"></i>
                  </span>
                </span>
                <!-- Controls -->
                <div style="margin-top: 7px">
                  <!-- Storage settings -->
                  <span data-tooltip="Change source storage filter">
                    <i class="fas fa-cog sup-button big"
                       @click="loadStorageSettings(); storage_settings.source.show=true"></i>
                  </span>
                  <!-- Delete tasks -->
                  <span v-if="project.can_delete_tasks">
                    <span style="margin-right: 15px"></span>
                    <span @click="deleteAllTasks()"
                          data-tooltip="Delete all tasks">
                      <i class="fas fa-trash-alt trash remove-task">&nbsp;&nbsp;</i>
                    </span>
                  </span>
                </div>
              </div> <!-- statistic -->
              
            </div>
          </div>
          
          <!-- Total completions -->
          <div class="column center aligned align-grid">
            <div class="ui db-card">
              <div class="ui statistic small">
                <!-- Project loading -->
                <center v-if="!project_loaded" style="margin-bottom: 3px">
                  <div class="ui loader loading active inline"></div>
                </center>
                <!-- Number -->
                <span class="value" v-else>
                  <animated-number :number="project.completion_count"></animated-number>
                </span>
                <span class="label">Completions</span>
                <span class="sub-label">
                  <i class="word-break" v-if="project.multi_session_mode">{{ project.target_storage.readable_path }}</i>
                  <span data-tooltip="Target storage sync in progress">
                    <i class="ui loader loading active inline mini" v-if="project.target_syncing"></i>
                  </span>
                </span>
                <!-- Controls -->
                <div style="margin-top: 7px">
                  <span data-tooltip="Change target storage">
                    <i class="fas fa-cog sup-button big"
                       @click="loadStorageSettings(); storage_settings.target.show=true"></i>
                  </span>
                </div>
              </div>
            </div>
          </div>
          
          <!-- Action Buttons -->
          <div class="column center aligned align-grid">
            <div class="ui db-card">
              <!-- Control buttons -->
              <div class="ui row stackable" v-if="project.task_count > 0">
                <div class="center aligned action-buttons">
                  <!-- Sampling -->
                  <span style="padding-top: 8px; padding-bottom: 11px;"
                        data-tooltip="Tasks sampling: selecting which task to take next in labeling. Edit project config file to change">
                    <span class="ui icon label">
                      <i class="ui icon far shuffle"></i>
                      {{ project.config['sampling'] }}
                    </span>
                  </span>                  
                  <!-- Start labeling -->
                  <a class="ui button positive" href="/">Start Labeling</a>                                    
                </div>
              </div>
            </div>
          </div>
        </div>

        <!-- Critical error -->
        <div v-if="error">
          <div class="ui hidden divier"></div>
          <div class="ui error message">
            <div class="header">{{ error.header }}</div>
            <div class="content">{{ error.message }}</div>
          </div>
          <div class="ui hidden divier"></div>
        </div>

        <!-- Import tasks -->
        <div class="row" v-if="project.task_count == 0">
          <a class="ui button positive" href="/import" v-if="project.can_manage_tasks">Import Tasks</a>
        </div>

      </div>
      <div class="ui divider hidden"></div>




      <!-- Table -->
      <div class="table-wrapper">
        <table v-if="project.task_count > 0" class="responsive">
        <!-- Header -->
        <tr>
          <th class="order" @click="changeOrder('id')">Task ID
            <i class="fas" :class="{'fa-sort-up': this.order=='id', 'fa-sort-down': this.order=='-id'}"></i>
          </th>
          <th class="order" @click="changeOrder('completed_at')">Completed at
            <i class="fas"
               :class="{'fa-sort-up': this.order=='completed_at', 'fa-sort-down': this.order=='-completed_at'}"></i>
          </th>
          <th class="order" @click="changeOrder('has_skipped_completions')">
            Skipped
            <i class="fas"
               :class="{'fa-sort-up': this.order=='has_skipped_completions', 'fa-sort-down': this.order=='-has_skipped_completions'}"></i>
          </th>
          <th>Label</th>
          <th v-if="project.can_delete_tasks || project.can_manage_completions">Delete</th>

          <!-- Label config fields -->
          <th v-for="(value, key) in project.data_types" v-if="value === 'Image'">${{ key }}</th>
        </tr>

        <!-- Task row -->

        <!-- Broken task -->
        <tr v-if="task == null" class="text-center" v-for="task in tasks">
          <td colspan="3"><small>broken task [backend returns null, check storage settings,
            may be you forgot "Generate task data with URLs ..." checkbox on source storage settings?]</small></td>
        </tr>

        <!-- Correct task -->
        <tr v-if="task != null" class="text-center" v-for="task in tasks">
          <!-- Task ID -->
          <td class="text-center">
            <span class="ui mini blue loader inline active" v-if="task.processing"></span>
            {{ task.id }}
          </td>
          <!-- Completed at -->
          <td>
           {{ task.completed_at }}
          </td>
          <!-- Skipped -->
          <td>
            <span style="cursor:pointer">
             <i class="ui icon forward grey" v-if="task.has_skipped_completions"></i>
           </span>
          </td>
          <!-- Label -->
          <td class="text-center">
            <a :href="'/?task_id=' + task.id">
              <i class="fas fa-eye eye show-completion"></i>
            </a>
          </td>
          <!-- Delete -->
          <td class="text-center" v-if="project.can_delete_tasks || project.can_manage_completions">
            <div class="actions-card">
              <span v-if="project.can_delete_tasks">
                <a class="trash" @click="deleteTask(task)" data-tooltip="Delete task">
                  <i class="fas fa-trash-alt trash remove-task"></i>
                </a>
              </span>
              <span v-if="project.can_manage_completions">
                <span v-if="task.completions">
                  <a class="trash" @click="deleteCompletion(task, task.completions[0])"
                     style="margin-left: 10px"
                     data-tooltip="Delete all completions of this task">
                    <i class="far fa-trash-alt trash remove-completion"></i>
                  </a>
                </span>
              </span>
            </div>
          </td>

          <!-- Label config fields -->
          <td v-for="(value, key) in project.data_types" v-if="value === 'Image'">
            <image-with-fade-in :src="task.data[key]"></image-with-fade-in>
          </td>
        </tr>

      </table>
      </div>
      <div class="ui divider hidden"></div>
      
      <!-- Pagination -->

      <!-- this element is needed for pretty symmetrical alignment with loader on the right side -->
      <span class="ui loader active blue tiny inline" style="opacity: 0; margin-left:10px"></span>

      <div class="ui pagination menu" v-if="project.task_count > 0">
        <a class="item" :class="{'active': page>1, 'disabled': page<=1}"
           @click="page!=1 ? page--: page">Prev</a>

        <div class="item">
          <input v-model="page" style="border:none" type="number" min="1" :max="totalPages">
          <span style="cursor:pointer" @click="page=totalPages">&nbsp; of &nbsp;&nbsp;
            {{ totalPages }}
          </span>
        </div>

        <div class="item">
          <select class="pagination-size" v-model="page_size">
            <option>1</option>
            <option>5</option>
            <option selected="selected">10</option>
            <option>50</option>
            <option>100</option>
          </select>
        </div>

        <!-- <div class="item"><span data-tooltip="Auto update project info and tasks by timer (about 5 sec)">
          <i class="far fa-clock" :style="{opacity: auto_update_timer ? 1.0: 0.5, cursor: 'pointer'}"
             @click="toggleAutoUpdateTimer()"></i>
        </span></div> -->

        <a class="item" :class="{'active': page<totalPages, 'disabled': page>=totalPages}"
           @click="page<totalPages ? page++: page">Next</a>
      </div> <!-- pagination -->

      <i class="ui loader active blue tiny inline"
            :style="{opacity: tasks_loaded ? 0: 0.5, 'margin-left': '10px'}"></i>

      <br/>
    </div>
    <br/><br/>
  </div>

  </center>

  {% endraw %}
  {% include 'includes/storages.html' %}
  {% raw %}

  </div>

  <script src="static/js/components/animatedNumber.js"></script>
  <script src="static/js/components/imageWithFadeIn.js"></script>
  <script src="static/js/components/vue-tippy.min.js"></script>
  <script>
      Vue.use(SemanticUIVue);
      Vue.use(VueTippy);

      var app = new Vue({
          el: '#app',

          data: function () {
              return {
                  // provided by api/project
                  project: {% endraw %}{{ serialized_project|json|safe }}{% raw %},

                  // provided by api/tasks
                  tasks: [],

                  // provided by api/project/storage-settings
                  storage_settings: {
                      source: {
                          fields: [], errors: [], type: 'json', storage_for: 'source',
                          show: false, loading: false, type_loading: false, save_success: false
                      },
                      target: {
                          fields: [], errors: [], type: 'json', storage_for: 'target',
                          show: false, loading: false, type_loading: false, save_success: false
                      }
                  },
                  storage_settings_all: {},

                  // internal variables
                  vue_loaded: false,
                  project_loaded: false,
                  tasks_loaded: false,
                  page: Cookies.get('page', 1),
                  page_size: Cookies.get('page_size', 10),
                  order: Cookies.get('order', 'id'),
                  auto_update_timer: null,
                  timer_interval: 5000,
                  error: null
              }
          },

          // components
          components: {
              'animated-number': animatedNumber,
              'image-with-fade-in': imageWithFadeIn
          },

          computed: {
              currentTasks: function () {
                  return this.tasks;
              },
              totalPages: function () {
                  var total = Math.ceil(this.project.task_count / parseInt(this.page_size));
                  if (this.page > total)
                      this.page = total;
                  return total;
              }
          },

          methods: {
              getApi: function (dst, url, always, fail, done) {
                  /* this api call will do vue.data['dst'] = get(url) */

                  var root = this;
                  $.get(url + (url.includes('?') ? '&' : '?') + 'rnd=' + randomInteger(0, 100000))
                      .done(function (data) {
                          setValue(root, dst, data);
                          if (done) done(data);
                          if (always) always(data);
                          // console.log(dst + ' loaded');
                      })
                      .fail(function (data) {
                          if (fail) fail(data);
                          else {
                              root.showError('Error while get api for <' + dst + '>:', message_from_response(data));
                          }
                          if (always) always(data);
                          console.log('error: no ' + dst + ' loaded')
                      })
              },

              // get tasks from api
              loadTasks: function () {
                  var root = this;
                  root.tasks_loaded = false;
                  this.getApi('tasks', '/api/tasks?page=' + this.page +
                                       '&page_size=' + parseInt(this.page_size) +
                                       '&order=' + this.order, null,
                      // fail
                      function(data) {
                        root.showError('Tasks loading error', message_from_response(data))
                      },

                      // always
                      function(data) {
                        root.tasks_loaded = true;
                      }
                  );
              },

              // get project info from api
              loadProject: function () {
                  var root = this;
                  this.getApi('project', '/api/project/',
                      // always
                      function () { root.project_loaded = true; },
                      // fail
                      function (data) {
                          root.showError('Project loading error', message_from_response(data));
                      }
                  );
              },

              // get tasks from api
              loadStorageSettings: function () {
                  var root = this;
                  root.storage_settings.source.type_loading = root.storage_settings.target.type_loading = true;
                  this.getApi('storage_settings_all', '/api/project/storage-settings',
                      function () {
                          root.storage_settings.source.type_loading = root.storage_settings.target.type_loading = false;
                          root.changeStorageSettings('source', 'current');
                          root.changeStorageSettings('target', 'current');
                      });
              },

              // get settings from storage_settings_all
              changeStorageSettings: function (storage_for, storage_type) {
                  // change to current on backend
                  if (storage_type === 'current') {
                      var storages = this.storage_settings_all[storage_for];
                      for (var type in storages) {
                          var value = storages[type];
                          if (value.current) {
                              storage_type = type;
                              setValue(this, 'storage_settings.'+storage_for, value);
                              break;
                          }
                      }
                  }
                  // change to new type
                  else {
                      var value = this.storage_settings_all[storage_for][storage_type];
                      setValue(this, 'storage_settings.'+storage_for, value);
                  }

                  // hide/show link to import page
                  if (storage_for === 'source') {
                      $('#menu-import').css("display", storage_type === 'tasks-json' ? 'block' : 'none');
                  }
              },

              saveStorageSettings: function(storage_for) {
                  var root = this;
                  root.storage_settings[storage_for].loading = true;
                  root.storage_settings[storage_for].save_success = false;
                  root.$set(root.storage_settings[storage_for], 'errors', []);
                  $.ajax({
                      type: 'POST',
                      url: '/api/project/storage-settings' +
                          '?type=' + this.storage_settings[storage_for].type +
                          '&storage_for=' + storage_for,
                      contentType: 'application/json',
                      dataType: 'json',
                      data: JSON.stringify(getFormData($('#' + storage_for + '-storage-form')))
                  }).fail(function (data) {
                      if (data.hasOwnProperty('responseJSON') && data.responseJSON.hasOwnProperty('errors'))
                          root.$set(root.storage_settings[storage_for], 'errors', data.responseJSON.errors);
                      else {
                          var msg = message_from_response(data);
                          root.storage_settings[storage_for].errors = {common: msg};
                          root.showError('Storage settings error', msg)
                      }
                      console.log('save storage settings error:');
                      console.log(data);
                  }).done(function() {
                      root.storage_settings[storage_for].save_success = true;
                      root.project_loaded = false;
                      setTimeout(function(){
                        root.loadAll();
                      }, 4000);
                  }).always(function () {
                      root.storage_settings[storage_for].loading = false;
                  });
                  return false;
              },

              // update all objects via api
              loadAll: function () {
                  this.loadProject();
                  this.loadTasks();
                  this.loadStorageSettings();
              },

              // update all objects via api
              loadProjectAndTasks: function () {
                  this.loadProject();
                  this.loadTasks();
              },

              // update all objects via api
              loadProjectAndTasksByTimer: function () {
                  if (this.project_loaded && this.tasks_loaded) {
                      this.loadProject();
                      this.loadTasks();
                  }
              },

              // change order of sorting in table
              changeOrder: function (name) {
                  console.log('order changed to ' + name);
                  var old = getUrlArg('order', 'id');
                  if (old === name) {
                      name = '-' + name;
                  }
                  this.order = name;
                  Cookies.set('order', name);
                  refreshHistoryArg('order', name);
                  this.loadTasks();
              },

              // delete completion with trash button
              deleteCompletion: function (task, completion) {
                  task.processing = true;
                  this.$forceUpdate();
                  var request = new XMLHttpRequest();
                  request.open("DELETE", "/api/tasks/" + task.id + "/completions/" + completion.id + "/", true);
                  request.onload = this.loadProjectAndTasks;
                  request.send();
              },

              // delete completion with trash button
              deleteTask: function (task) {
                  task.processing = true;
                  this.$forceUpdate();
                  var request = new XMLHttpRequest();
                  request.open("DELETE", "/api/tasks/" + task.id + "/", true);
                  request.onload = this.loadProjectAndTasks;
                  request.send();
              },

              // delete all tasks from project
              deleteAllTasks: function () {
                  var deletion_confirmed = confirm(
                      'You are going to delete all existing tasks.\n' +
                      'Warning! this operation cannot be undone.\nPlease confirm your action.');
                  if (deletion_confirmed) {
                      var request = new XMLHttpRequest();
                      request.open("DELETE", "/api/tasks/delete", true);
                      request.onload = this.loadProjectAndTasks;
                      request.send();
                  }
              },

              // start timer with project & task api loading
              toggleAutoUpdateTimer: function () {
                  if (this.auto_update_timer) {
                    clearInterval(this.auto_update_timer);
                    this.auto_update_timer = null;
                  }
                  else {
                    this.auto_update_timer = setInterval(this.loadProjectAndTasksByTimer, this.timer_interval);
                  }
              },

              capitalizeFirstLetter: capitalizeFirstLetter,  // from helpers.js

              getCurrentStorage: function (storage_for) {
                  var all = this.storage_settings_all[storage_for];
                  for (var key in all)
                      if (all[key].current)
                          return all[key];
                  return {description: '[No storage defined]', name: '[No storage defined]'}
              },

              showStorageField: function(field_name, storage) {
                if (field_name !== 'create_local_copy') {
                    // find field use_blob_urls inside of list
                    var use_blob_urls = null;
                    for (var i in storage.fields) {
                        if (storage.fields[i].name === 'use_blob_urls') {
                            use_blob_urls = storage.fields[i];
                            break;
                        }
                    }
                    if (field_name === 'data_key' && !use_blob_urls.data) {
                      return false;
                    }
                    return true;
                }
              },

              showError: function(title, message) {
                  $('body').toast({
                      class: 'error',
                      title: title,
                      message: message,
                      displayTime: this.timer_interval * 2,
                      position: 'bottom center'
                  })
              }
          },

          watch: {
              // watch for page variable changes
              page: function () {
                  this.loadTasks();
                  Cookies.set('page', this.page);
                  refreshHistoryArg('page', this.page);
              },
              page_size: function () {
                  this.loadTasks();
                  Cookies.set('page_size', this.page_size);
                  refreshHistoryArg('page_size', this.page_size);
              },
              'storage_settings.source.type': function () {
                 this.changeStorageSettings('source', this.storage_settings.source.type)
              },
              'storage_settings.target.type': function () {
                 this.changeStorageSettings('target', this.storage_settings.target.type)
              }
          },

          // vue mounting of page
          mounted: function () {
              this.vue_loaded = true;
              this.project_loaded = true;

              this.order = getUrlArg('order', this.order);
              this.page = getUrlArg('page', this.page);
              this.page_size = getUrlArg('page_size', this.page_size);
              this.loadAll();

              this.timer_interval = parseInt(getUrlArg('timer', '5000'));
              if (this.timer_interval > 0)
                this.toggleAutoUpdateTimer();

              $('#vue_loader').hide();
              console.log('Vue mounting success');
          }
      });

  </script>

{% endraw %}
{% endblock %}
